home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / wasm223.zip / AUTOPARK.ASM < prev    next >
Assembly Source File  |  1993-05-04  |  17KB  |  529 lines

  1. ;********************************************************
  2. ; AutoPark by Eric Tauck
  3. ;
  4. ; This TSR parks a hard disk in the background after
  5. ; a specified period of disk inactivity.  AutoPark may
  6. ; be installed multiple times for multiple hard disks.
  7. ; AutoPark does not check to see if a drive is valid.
  8. ;
  9. ; Usage: AUTOPARK drive time     install
  10. ;        AUTOPARK                park
  11. ;        AUTOPARK PARK           park
  12. ;        AUTOPARK ENABLE         enable
  13. ;        AUTOPARK DISABLE        disable
  14. ;
  15. ;        drive = hard disk drive letter
  16. ;        time = minutes of inactivity
  17. ;
  18. ; The disable, enable, and park options affect all
  19. ; resident copies of AutoPark.
  20. ;
  21. ; AutoPark can interfere with applications that access
  22. ; the hard disk at a low level.  A new feature of version
  23. ; 2.00 is the ability to enable and disable all resident
  24. ; copies of AutoPark, and I recommend using this feature
  25. ; for any applications that reformat, defragment, or
  26. ; continuously read or write to the hard disk (like a
  27. ; backup program).
  28. ;
  29. ; AutoPark uses a special interrupt to communicate with
  30. ; resident copies of AutoPark.  This interrupt may be
  31. ; used by other TSR's if they are installed BEFORE
  32. ; AutoPark, or by regular applications as long as the
  33. ; interrupt is restored when the application terminates.
  34. ; The interrupt is only necessary perform a forced park,
  35. ; enable, or disable resident copies of AutoPark.  The
  36. ; interrupt (EQUated at the start of the code) can be
  37. ; changed to any non-reserved interrupt: 60 to 66 or F1
  38. ; to FF.
  39. ;
  40. ; Note: I looked at several other hard disk parking
  41. ; utilities in order to determine the the best way to
  42. ; park a hard disk.  This program appears to work on my
  43. ; computer, but I don't guarantee it will work on all
  44. ; computers.
  45. ;
  46. ; This code is written for WASM and requires several of
  47. ; the WASM library files.
  48. ;
  49. ;--------------------------------------------------------
  50. ;
  51. ; Version 1.10
  52. ;
  53. ;   The disk handler now checks to see if the drive to
  54. ;   be parked is being accessed.  Previously, any
  55. ;   INT 13 call was assumed to unpark the drive.
  56. ;
  57. ; Version 1.20
  58. ;
  59. ;   The disk handler now prevents a park attempt when
  60. ;   accessing another drive (this caused AutoPark to
  61. ;   crash the system).  The INT 1C handler has also been
  62. ;   rewritten.
  63. ;
  64. ; Version 1.21
  65. ;
  66. ;   The relocation address is changed to 5CH (from 80H),
  67. ;   which overwrites the PSP FCB's and shrinks AutoPark's
  68. ;   resident size a little.
  69. ;
  70. ; Version 1.22
  71. ;
  72. ;   Slightly changed the messages.
  73. ;
  74. ; Version 2.00
  75. ;
  76. ;   Added park, disable, and enable options.  A colon is
  77. ;   allowed in the drive name.  The interrupt handlers
  78. ;   have been rewritten to make the code a little smaller
  79. ;   and faster.
  80. ;
  81. ; Version 2.01
  82. ;
  83. ;   All disks are parked if installed and no command line
  84. ;   options.
  85.  
  86. C_INT   EQU     0F7H            ;chain interrupt, can be changed
  87.  
  88.         jmp     Install         ;goto installation
  89.  
  90. CODE_BEGIN                      ;start of code to relocate
  91.  
  92. NEWADDR EQU     5CH             ;new address
  93. RELOC   EQU     $ - NEWADDR     ;displacement
  94.  
  95. drive   DB      ?               ;drive to park
  96. time    DW      ?               ;timer setting
  97. count   DW      ?               ;timer count
  98. block   DB      0               ;block (reentrancy) flag
  99.  
  100. old13   LABEL   DWORD           ;original interrupt 13H
  101.         DW      ?
  102.         DW      ?
  103.  
  104. old1C   LABEL   DWORD           ;original interrupt 1CH
  105.         DW      ?
  106.         DW      ?
  107.  
  108. chain   LABEL   DWORD           ;chain interrupt (for resident AutoParks)
  109.         DW      ?
  110.         DW      ?
  111.  
  112. ;--- chain the chain interrupt (for other applications using this interrupt)
  113.  
  114. chain_jump
  115.         seg     cs
  116.         jmp     chain           ;jump to previous handler
  117.  
  118. ;========================================
  119. ; Disk handler.
  120.  
  121. Disk    PROC    FAR
  122.         jmps    disk1                   ;change offset to 0 to ENABLE
  123.  
  124.         seg     cs
  125.         cmp     dl, drive - RELOC       ;check if drive to park
  126.         jne     disk1                   ;skip if not
  127.  
  128.         seg     cs
  129.         push    time - RELOC
  130.         seg     cs
  131.         pop     count - RELOC           ;reset timer
  132.  
  133. disk1   seg     cs
  134.         inc     block - RELOC
  135.         pushf
  136.         seg     cs
  137.         call    old13 - RELOC           ;call original
  138.         seg     cs
  139.         dec     block - RELOC
  140.         ret     2
  141.         ENDP
  142.  
  143. ;========================================
  144. ; Timer handler.
  145.  
  146. Timer   PROC    FAR
  147.         jmps    timer1                  ;change offset to 0 to ENABLE
  148.  
  149.         seg     cs
  150.         cmp     count - RELOC, 0        ;check if count zero
  151.         je      timer1
  152.         seg     cs
  153.         dec     count - RELOC           ;decrement count
  154.         jnz     timer1
  155.         seg     cs
  156.         cmp     block - RELOC, 0        ;check if blocked
  157.         je      Park
  158.         seg     cs
  159.         inc     count - RELOC           ;reset count to one
  160.  
  161. timer1  seg     cs
  162.         jmp     old1C - RELOC           ;chain to original
  163.  
  164. ;----------------------------------------
  165. ; Park the disk drive.
  166.  
  167. Park    sti
  168.         push    ax
  169.         push    bx
  170.         push    cx
  171.         push    dx
  172.  
  173.         mov     al, 20H                 ;@@@ TIMEPARK does this @@@
  174.         out     20H, al                 ;
  175.  
  176.         mov     ah, 8                   ;read drive parameters
  177.         seg     cs
  178.         mov     dl, drive - RELOC       ;drive number
  179.         pushf
  180.         seg     cs
  181.         call    old13 - RELOC           ;execute
  182.  
  183. ;       and     cl, 0C0H                ;@@@ Northgate PARK does this @@@
  184. ;       inc     cl                      ;
  185.  
  186.         inc     ch                      ;cylinder after last cylinder
  187.         jnz     park1                   ;skip if no carry
  188.         add     cl, 40H                 ;carry
  189.  
  190. park1   mov     ah, 0CH                 ;seek function
  191. ;       mov     al, 1                   ;@@@ TIMEPARK does this @@@
  192.         seg     cs
  193.         mov     dl, drive - RELOC       ;drive
  194.         sub     dh, dh                  ;head zero
  195.         pushf
  196.         seg     cs
  197.         call    old13 - RELOC           ;execute
  198.  
  199.         pop     dx
  200.         pop     cx
  201.         pop     bx
  202.         pop     ax
  203.         jmps    timer1
  204. ParkX                                   ;end of Park
  205.  
  206.         ENDP
  207.  
  208. CODE_END
  209.  
  210. ;========================================
  211. ; Install.
  212.  
  213. ;--- installation data
  214.  
  215. banner  DB      10,13, 'AutoPark  Version 2.01  Eric Tauck', 0
  216.  
  217. smess1  DB      'Drive C: will be parked after ', 0
  218. smess2  DB      ' minute(s)', 0
  219.  
  220. optmes1 DB      'ENABLE',0
  221. optmes2 DB      'DISABLE',0
  222. optmes3 DB      'PARK',0
  223.  
  224. hmess   DB      10,13
  225.         DB      'Usage: AUTOPARK drive time     install',13,10
  226.         DB      '       AUTOPARK PARK           park',13,10
  227.         DB      '       AUTOPARK ENABLE         enable',13,10
  228.         DB      '       AUTOPARK DISABLE        disable',13,10
  229.         DB      10,13
  230.         DB      '       drive = hard disk drive letter',13,10
  231.         DB      '       time = minutes of inactivity'
  232.         DB      0
  233.  
  234. emess   DB      'Error in parameters, run "AUTOPARK ?" for help', 0
  235.  
  236. rmess1  DB      'Cannot enable, AutoPark is not resident',0
  237. rmess2  DB      'Cannot disable, AutoPark is not resident',0
  238. rmess3  DB      'Hard disk parking enabled',0
  239. rmess4  DB      'Hard disk parking disabled',0
  240. rmess5  DB      'Cannot park, AutoPark is not resident',0
  241. rmess6  DB      'Parking all hard disks',0
  242.  
  243. ;=== entry point
  244.  
  245. Install
  246.  
  247.         INCLUDE 'library\case1.asm'
  248.         INCLUDE 'library\case2.asm'
  249.         INCLUDE 'library\convert.asm'
  250.         INCLUDE 'library\message1.asm'
  251.         INCLUDE 'library\intr.asm'
  252.         INCLUDE 'library\parms.asm'
  253.         INCLUDE 'library\string.asm'
  254.  
  255.         jmp     inst1                   ;skip error and help messages
  256.  
  257. ;--- help
  258.  
  259. help    mov     ax, OFFSET hmess
  260.  
  261. exit    call    MesPutL
  262.         mov     ax, 4C00H
  263.         int     21H
  264.  
  265. ;--- enable
  266.  
  267. enable  mov     ax, OFFSET R_Enable     ;enable routine
  268.         call    Resident                ;set resident options
  269.         mov     ax, OFFSET rmess1
  270.         jz      error2
  271.         mov     ax, OFFSET rmess3
  272.         jmps    exit
  273.  
  274. ;--- disable
  275.  
  276. disable mov     ax, OFFSET R_Disable    ;disable routine
  277.         call    Resident                ;set resident options
  278.         mov     ax, OFFSET rmess2
  279.         jz      error2
  280.         mov     ax, OFFSET rmess4
  281.         jmps    exit
  282.  
  283. ;--- forced park
  284.  
  285. forced  mov     ax, OFFSET R_Park       ;park routine
  286.         call    Resident                ;set resident options
  287.         mov     ax, OFFSET rmess5
  288.         jz      error2
  289.         mov     ax, OFFSET rmess6
  290.         jmps    exit
  291.  
  292. ;--- error
  293.  
  294. error1  mov     ax, OFFSET emess
  295.  
  296. error2  call    MesPutL
  297.         mov     ax, 4CFFH
  298.         int     21H
  299.  
  300. ;--- begin installation, show banner
  301.  
  302. inst1   mov     ax, OFFSET banner
  303.         call    MesPutL
  304.  
  305. ;--- get first option
  306.  
  307.         call    ParGet                  ;get drive
  308.         jc      forced                  ;park if no parameter
  309.         mov     si, ax
  310.         cmp     BYTE [si], '?'          ;check if help request
  311.         je      help                    ;jump if so
  312.         call    StrUpr                  ;convert to upper case
  313.  
  314.         mov     ax, si
  315.         mov     bx, OFFSET optmes1      ;ENABLE string
  316.         call    StrCmp                  ;check if enable
  317.         jnc     enable
  318.  
  319.         mov     ax, si
  320.         mov     bx, OFFSET optmes2      ;DISABLE string
  321.         call    StrCmp                  ;check if disable
  322.         jnc     disable
  323.  
  324.         mov     ax, si
  325.         mov     bx, OFFSET optmes3      ;PARK string
  326.         call    StrCmp                  ;check if disable
  327.         jnc     forced 
  328.  
  329.         mov     ax, si
  330.         call    StrLen                  ;get length
  331.         dec     ax                      ;check if just one character
  332.         jz      inst2
  333.         dec     ax                      ;check if two characters
  334.         jnz     error1                  ;jump if not
  335.         cmp     BYTE [si+1], ':'        ;check if second character is colon
  336.         jne     error1
  337. inst2   mov     al, [si]                ;load drive letter
  338.         sub     al, 'C'                 ;convert to number, C = 0, D = 1, etc
  339.         cmp     al, 25                  ;check range
  340.         ja      error1
  341.  
  342.         add     smess1 + 6, al          ;set drive letter in message
  343.         or      al, 80H                 ;must set high bit for parking
  344.         mov     drive, al               ;save it
  345.  
  346. ;--- get timer value
  347.  
  348.         call    ParGet                  ;get time
  349.         jc      error1                  ;jump if none
  350.         push    ax                      ;save for display
  351.         mov     cx, 10                  ;base 10
  352.         call    Str2Num                 ;convert to number
  353.         jc      error1                  ;jump if bad number
  354.         or      ax, ax                  ;check if zero
  355.         jz      error1
  356.         or      dx, dx                  ;check if too big
  357.         jnz     error1
  358.         mov     cx, 1092                ;ticks per minute
  359.         mul     cx                      ;convert minutes to ticks
  360.         or      dx, dx                  ;check if too big
  361.         jnz     error1                  ;jump if so
  362.  
  363.         mov     time, ax                ;save timer value
  364.         mov     count, ax               ;save current value
  365.  
  366. ;--- display success message
  367.  
  368.         mov     ax, OFFSET smess1
  369.         call    MesPut
  370.         pop     ax
  371.         call    MesPut
  372.         mov     ax, OFFSET smess2
  373.         call    MesPutL
  374.  
  375. ;--- save old interrupts
  376.  
  377.         mov     al, 13H                 ;disk handler
  378.         call    IntGet                  ;get interrupt
  379.         mov     WORD old13, bx          ;save offset
  380.         mov     WORD old13+2, dx        ;save segment
  381.  
  382.         mov     al, 1CH                 ;timer tick
  383.         call    IntGet                  ;get interrupt
  384.         mov     WORD old1C, bx          ;save offset
  385.         mov     WORD old1C+2, dx        ;save segment
  386.  
  387.         mov     al, C_INT               ;chain interrupt
  388.         call    IntGet                  ;get interrupt
  389.         cmp     bx, OFFSET chain_jump - RELOC ;check if same offset
  390.         jne     inst3
  391.         mov     ax, cs
  392.         cmp     dx, ax                  ;check if same segment
  393.         jne     inst3
  394.         sub     bx, bx                  ;zero offset
  395.         mov     dx, bx                  ;zero segment
  396. inst3   mov     WORD chain, bx          ;save offset
  397.         mov     WORD chain+2, dx        ;save segment
  398.  
  399. ;--- copy code
  400.  
  401.         mov     si, OFFSET CODE_BEGIN                   ;current address
  402.         mov     di, NEWADDR                             ;new address
  403.         mov     cx, OFFSET CODE_END - OFFSET CODE_BEGIN ;bytes of code
  404.         cld
  405.         rep                                             ;
  406.         movsb                                           ;copy code
  407.  
  408. ;--- hook new interrupts
  409.  
  410.         mov     al, 13H                         ;disk handler
  411.         mov     dx, cs                          ;segment
  412.         mov     bx, OFFSET Disk - RELOC         ;offset
  413.         call    IntSet                          ;set interrupt
  414.  
  415.         mov     al, 1CH                         ;disk handler
  416.         mov     dx, cs                          ;segment
  417.         mov     bx, OFFSET Timer - RELOC        ;offset
  418.         call    IntSet                          ;set interrupt
  419.  
  420.         mov     al, C_INT                       ;chain interrupt
  421.         mov     dx, cs                          ;segment
  422.         mov     bx, OFFSET chain_jump - RELOC   ;offset
  423.         call    IntSet                          ;set interrupt
  424.  
  425. ;--- enable the handlers
  426.  
  427.         mov     BYTE [OFFSET Disk - RELOC + 1], 0   ;enable disk interrupt
  428.         mov     BYTE [OFFSET Timer - RELOC + 1], 0  ;enable timer interrupt
  429.  
  430. ;--- release environment
  431.  
  432.         push    es
  433.         mov     ah, 49H                         ;release function
  434.         mov     es, [2CH]                       ;environment segment
  435.         int     21H                             ;execute
  436.         mov     WORD [2CH], 0                   ;zero address
  437.         pop     es
  438.  
  439. ;--- terminate
  440.  
  441.         mov     ax, OFFSET CODE_END - RELOC     ;bytes to reserve
  442.         mov     dx, ax
  443.         mov     cl, 4                           ;bits to shift
  444.         shr     dx, cl                          ;convert to paragraph
  445.         test    ax, 0FH                         ;check if extra bits
  446.         jz      inst4                           ;skip if not
  447.         inc     dx                              ;round paragraph up
  448. inst4   mov     ax, 3100H                       ;TSR with error code 0
  449.         int     21H                             ;execute
  450.  
  451. ;========================================
  452. ; Send options to resident AutoParks.
  453. ;
  454. ; In: AX= resident routine.
  455. ;
  456. ; Out: ZF= set if no resident AutoParks.
  457.  
  458. Resident PROC   NEAR
  459.         push    ax
  460.         mov     al, C_INT                       ;interrupt
  461.         call    IntGet                          ;get segment
  462.         pop     bp
  463.  
  464.         sub     bx, bx                          ;count instances
  465.         or      dx, dx                          ;check if zero (not set
  466.         jz      resid3
  467.  
  468.         push    ds
  469.         mov     ds, dx                          ;load segment
  470.         jmps    resid2
  471.  
  472. ;--- set resident option
  473.  
  474. resid1  call    bp                              ;call enable/disable
  475.         inc     bx                              ;increment pointer
  476.  
  477. ;--- next installation
  478.  
  479.         mov     ds, WORD chain - RELOC + 2      ;new segment
  480.  
  481. ;--- check if pointing to resident AutoPark
  482.  
  483. resid2  mov     si, OFFSET Park - RELOC         ;potential resident offset
  484.         mov     di, OFFSET Park                 ;local offset
  485.         mov     cx, OFFSET ParkX - OFFSET Park  ;bytes to compare
  486.         cld
  487.         rep
  488.         cmpsb                                   ;compare code
  489.         je      resid1
  490.         pop     ds
  491.  
  492. resid3  or      bx, bx                          ;set ZF
  493.         ret
  494.         ENDP
  495.  
  496. ;========================================
  497. ; Resident routines.
  498.  
  499. ;--- disable routine
  500.  
  501. R_Disable PROC  NEAR
  502.         seg     es
  503.         mov     al, [OFFSET Disk + 1]           ;load enable byte
  504.         mov     [OFFSET Disk - RELOC + 1], al   ;disable disk interrupt
  505.         seg     es
  506.         mov     al, [OFFSET Timer + 1]          ;load enable byte
  507.         mov     [OFFSET Timer - RELOC + 1], al  ;disable timer interrupt
  508.         ret
  509.         ENDP
  510.  
  511. ;--- enable routine
  512.  
  513. R_Enable PROC   NEAR
  514.         mov     BYTE [OFFSET Disk - RELOC + 1], 0  ;enable disk interrupt
  515.         mov     BYTE [OFFSET Timer - RELOC + 1], 0 ;enable timer interrupt
  516.         mov     ax, time - RELOC
  517.         mov     count - RELOC, ax               ;reset timer
  518.         ret
  519.         ENDP
  520.  
  521. ;--- forced park
  522.  
  523. R_Park  PROC    NEAR
  524.         mov     BYTE [OFFSET Disk - RELOC + 1], 0  ;enable disk interrupt
  525.         mov     BYTE [OFFSET Timer - RELOC + 1], 0 ;enable timer interrupt
  526.         mov     count - RELOC, 1                   ;set timer, one tick
  527.         ret
  528.         ENDP
  529.